/**
 * Paquete que contiene los objetos.
 */
package co.sumset.objetos;

import java.awt.event.KeyEvent;

/**
 * La Clase Agente no es mas que un actor, que ademas puede ser controlado
 * por el usuario mediante el teclado o el raton.
 * 
 * @author Cristian Raul Pineda Rodriguez
 */
public class Agente extends Actor {

	protected static final int AGENTE_SPEED = 5;// Velocidad del Hilo para el Agente
	protected int vx;//Velocidad en X
	protected int vy;//Velocidad en Y

	private boolean up,down,left,right;//Direcciones para mover el Agente

	private int clusterBombs;//Cantidad de bombas
	private int score;//Puntaje de juego
	private int shields;//Puntaje de vida


	/**
	 * Metodo Constructor. Inicializa el Escenario.
	 * @param stage Instancia de la clase Stage
	 */
	public Agente(Escenario stage) {
		super(stage);
		setSpriteNames( new String[] {"/juego/sol01.png","/juego/sol02.png"});
		clusterBombs=stage.getAdministrador().getNivel().getNum_bomba();
		shields = stage.MAX_SHIELDS;
		score = 0;
	}

	/**
	 * Este metodo permite ejecutar acciones para un Agente
	 */
	public void act() {
		super.act();
		setFrameSpeed(25);
		$varX+=vx;
		$varY+=vy;
		if ($varX < 0 ) {
			$varX = 0;
		}
		if ($varX > Escenario.WIDTH - getWidth()){
			$varX = Escenario.WIDTH - getWidth();
		}
		if ($varY < 0 ){
			$varY = 0;
		}
		if ( $varY > Escenario.LIMITE-getHeight()){
			$varY = Escenario.LIMITE - getHeight();
		}
	}

	/**
	 * @return the vx
	 */
	public int getVx() {
		return vx;
	}

	/**
	 * @param vx the vx to set
	 */
	public void setVx(int vx) {
		this.vx = vx;
	}

	/**
	 * @return the vy
	 */
	public int getVy() {
		return vy;
	}

	/**
	 * @param vy the vy to set
	 */
	public void setVy(int vy) {
		this.vy = vy;
	}

	/**
	 * Este metodo permite acturalizar la velocidad del Agente
	 */
	protected void updateSpeed() {
		vx=0;vy=0;
		if (down) vy = AGENTE_SPEED;
		if (up) vy = -AGENTE_SPEED;
		if (left) vx = -AGENTE_SPEED;
		if (right) vx = AGENTE_SPEED;
	}

	/**
	 * Metodo que permite enviar los eventos de teclado al agente para que
	 * ejecute acciones, teclas de movimiento.
	 * @param e : Evento de teclado
	 */
	public void keyReleased(KeyEvent e) {
		switch (e.getKeyCode()) {
		case KeyEvent.VK_DOWN : down = false;break;
		case KeyEvent.VK_UP : up = false; break;
		case KeyEvent.VK_LEFT : left = false; break; 
		case KeyEvent.VK_RIGHT : right = false;break;
		}
		updateSpeed();
	}

	/**
	 * Metodo que permite enviar los eventos de teclado, 
	 * el agente tiene una teclas asignadas.
	 * 
	 * @param e Evento de teclado
	 */
	public void keyPressed(KeyEvent e) {
		switch (e.getKeyCode()) {
		case KeyEvent.VK_UP : up = true; break;
		case KeyEvent.VK_LEFT : left = true; break;
		case KeyEvent.VK_RIGHT : right = true; break;
		case KeyEvent.VK_DOWN : down = true;break;
		case KeyEvent.VK_SPACE : fire(); break;
		case KeyEvent.VK_B : fireCluster(); break;
		}
		updateSpeed();
	}

	/**
	 * Metodo que permite simular el comportamiento y la creacion de la Bala.
	 * 
	 */
	public void fire() {
		Bala b = new Bala(stage);
		b.set$varX($varX);
		b.set$varY($varY - b.getHeight());
		stage.addActor(b);
		stage.getSoundCache().playSound("missile.wav");
	}

	/**
	 * Metodo que permite simular el comportamiento y la creacion de una Bomba.
	 * 
	 */
	public void fireCluster() {
		if (clusterBombs == 0)
			return;

		clusterBombs--;
		stage.addActor( new Bomba(stage, Bomba.UP_LEFT, $varX,$varY,"/juego/bombUL.gif"));
		stage.addActor( new Bomba(stage, Bomba.UP,$varX,$varY,"/juego/bombU.gif"));
		stage.addActor( new Bomba(stage, Bomba.UP_RIGHT,$varX,$varY,"/juego/bombUR.gif"));
		stage.addActor( new Bomba(stage, Bomba.LEFT,$varX,$varY,"/juego/bombL.gif"));
		stage.addActor( new Bomba(stage, Bomba.RIGHT,$varX,$varY,"/juego/bombR.gif"));
		stage.addActor( new Bomba(stage, Bomba.DOWN_LEFT,$varX,$varY,"/juego/bombDL.gif"));
		stage.addActor( new Bomba(stage, Bomba.DOWN,$varX,$varY,"/juego/bombD.gif"));
		stage.addActor( new Bomba(stage, Bomba.DOWN_RIGHT,$varX,$varY,"/juego/bombDR.gif"));
	}
	/**
	 * @return the score
	 */
	public int getScore() {
		return score;
	}

	/**
	 * @param score the score to set
	 */
	public void setScore(int score) {
		this.score = score;
	}

	/**
	 * Metodo que permite aumentar el puntaje.
	 * @param i
	 */
	public void addScore(int i) { 
		score += i;  
	}

	/**
	 * @return the shields
	 */
	public int getShields() {
		return shields;
	}

	/**
	 * @param shields the shields to set
	 */
	public void setShields(int shields) {
		this.shields = shields;
	}

	/**
	 * Metodo que permite simular el comportamiento y la creacion de la Bala.
	 * 
	 */
	public void addShields(int i) {
		shields += i;
		if (shields > Escenario.MAX_SHIELDS){ 
			shields = Escenario.MAX_SHIELDS;
		}
	}

	/**
	 * Este metodo permite verificar las collisiones con otros Actores
	 * en el caso del Agente si los Actores son: Virus y Laser; si estos
	 * colisionan con el Agente mueren pero le restan puntos de vida al
	 * jugador y si el puntaje de vida es menor que cero se pinta el
	 * titulo de "Game Over".
	 * 
	 * @param a ; Recibe los actores que colisionan en el Escenario con el Agente
	 */
	public void collision(Actor a) {
		if (a instanceof Virus ) {
			a.remove();
			addScore(40);
			addShields(-40);
		}
		if (a instanceof Laser ) {
			a.remove();
			addShields(-10);
		}
		if (getShields() < 0){
			stage.gameOver();
		}
	}

	/**
	 * @return the clusterBombs
	 */
	public int getClusterBombs() {
		return clusterBombs;
	}

	/**
	 * @param clusterBombs the clusterBombs to set
	 */
	public void setClusterBombs(int clusterBombs) {
		this.clusterBombs = clusterBombs;
	}
}
